
package com.mixsmart.security;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;
import java.util.Base64;

/**
 * @author 乌草坡
 * @since 6.5.1
 */
public final  class KeyGeneratorUtils {

	private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqyFadDS3Gi38XOKXqIkmC4sLKOtTcqaUvHMcSLLJjmL4yx6U9mbdFQ+9t4GA+P1IiprmGW9qJJ35QEgKF3yEBlpBGUFdxdaQHHcfJSoMXI7kQZkkbypG1GQ31C8qIn23AUYlLi7eZTpmS1Y4weawqEUB9P9Fth4BKZS1/z97GH9bZXafTiv8ZnFsHEmd1Y9PLmxBxOUwv1oj9zXwnLH+Ca4AE4FtURM90eF5+DpWsp93J2FRb2/rYIkqOYpZxFJ8O6idE+1MQnd+clZI6d36cM/fjQ6FRiEJ1kpwD1u9jXedwqpapUUKlqX4c57pBDqK9P8twpxyAxjTewnZQo1NAwIDAQAB";

	private static final String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrIVp0NLcaLfxc4peoiSYLiwso61NyppS8cxxIssmOYvjLHpT2Zt0VD723gYD4/UiKmuYZb2oknflASAoXfIQGWkEZQV3F1pAcdx8lKgxcjuRBmSRvKkbUZDfULyoifbcBRiUuLt5lOmZLVjjB5rCoRQH0/0W2HgEplLX/P3sYf1tldp9OK/xmcWwcSZ3Vj08ubEHE5TC/WiP3NfCcsf4JrgATgW1REz3R4Xn4Olayn3cnYVFvb+tgiSo5ilnEUnw7qJ0T7UxCd35yVkjp3fpwz9+NDoVGIQnWSnAPW72Nd53CqlqlRQqWpfhznukEOor0/y3CnHIDGNN7CdlCjU0DAgMBAAECggEARpwHd4U8u6eXxjeUfezA7uhbHXIjx12mZy9Tz0c91OtPXnfq3NRKimMpU2sy7QmNAeux33LSJ/OqoXRX/aLZ0skwrRwEdhn28lfQWQRFf3dSBSMMHnYiLYaAZqNjTkHy3aq0sp6SEtCK3rDf0FnAMF3w1cbyW5d7wU1j3sKxpsRPlocOZ1BD+NsuOMsOat/jTskEZPCsEu4unWEzWf7H1qsroM7M1G0GOeplXpsjobqF8Fzb3pSSNhIlXk0iSz0n2OANmWrLf8gvLDHIA5tlTNt8nsiWGKOm+GtkGMTIbh4P61+6YB3IE1M7U9DlvzltqQJ/c1V37BKQeBvmG3UEcQKBgQC3dnsmPKXyn0xo5M9DBdVMTJhXOd+g5Eb+3cfk8t4+fvo1Trs8Wx1dfTQuH/MIo2AHDihTRcdvhh1XA7w5BTypWYssKVRUdAJnIBZdBefPUR6zoDCfBo74pCGTOwANKrDEvhFvbuIW0ECvt0C+QfQIfEUCBec9kvsQje2RMMlM+wKBgQDuypzxzIfL3xEG2jIoFluYFjmjduTfNA2+VoqyEJnNN69n7ql9jCq8A/kzaQQr4nKvvMwUv0DPvp9U1snfHe6ShCBj7E6uL08SVod9pHFiOrtt7WeK9HOTy0IbQ3mHBmbLS8Y9fhbCWKGQgWeSbpgR4na95FQUUgZywwkBI3LxmQKBgQCLR72yh7SMf3do4tyey1zlcfjtr5gg820arJDHNcKXu5qEweLPrXSbtyPYKJU/Z5jNgmgG4CDKgAziNIm+2ET3ZG2N90p4WyI/3FJeCM+1yqX+RIzlDfuYtDJxLgeZ92D/3DQsXwfxveR+Aid6yWNU1dMl+AlX67ADH1zOLzWD5QKBgQCW9HMe0KOQGCYVZN6MRQYGMRai5cht6eQ+TUtEogX4m5lBZLi062Ugkop5G4xNicvimMGS5Ay+x8zFvzrC15M4AFrRkFN0/edIunbQ0KH07RgLuCbaywo9hiL2RUOQPlXBcteRjCIrHgiU55loEo4D0FwsUylr5ya4ad9JXvWNEQKBgCStPjyGAHJhmKbtRvCdGb96S4oFWvQpwx125CFrBAn45Ud03Ac2iGBg47+j+Y4dQWLbeMMGgf+kS3Uke2ldj79qdwAX3EC+DNLv5AVgN5BH532nqz8s3MZMov+eouTGy11kqfkJiV22BSWUm1IBuoE2KLHiTIThltmr0KD9W4cq";

	private static final int INITIALIZE_LENGTH = 1024;

	private KeyGeneratorUtils() {
	}

	public static SecretKey generateSecretKey() {
		SecretKey hmacKey;
		try {
			hmacKey = KeyGenerator.getInstance("HmacSha256").generateKey();
		} catch (Exception ex) {
			throw new IllegalStateException(ex);
		}
		return hmacKey;
	}

	public static KeyPair generateRsaKeyPair() {
		KeyPair keyPair;
		try {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			keyPairGenerator.initialize(INITIALIZE_LENGTH);
			keyPair = keyPairGenerator.generateKeyPair();
		} catch (Exception ex) {
			throw new IllegalStateException(ex);
		}
		return keyPair;
	}

	public static KeyPair loadRsaKey() {
		KeyPair keyPair;
		try {
			byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_KEY);
			PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

			byte[] publicKeyBytes = Base64.getDecoder().decode(PUBLIC_KEY);
			X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
			PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
			keyPair = new KeyPair(publicKey, privateKey);

		} catch (Exception ex) {
			throw new IllegalStateException(ex);
		}
		return keyPair;
	}

	public static KeyPair generateEcKey() {
		EllipticCurve ellipticCurve = new EllipticCurve(
				new ECFieldFp(new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951")),
				new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853948"),
				new BigInteger("41058363725152142129326129780047268409114441015993725554835256314039467401291"));
		ECPoint ecPoint = new ECPoint(
				new BigInteger("48439561293906451759052585252797914202762949526041747995844080717082404635286"),
				new BigInteger("36134250956749795798585127919587881956611106672985015071877198253568414405109"));
		ECParameterSpec ecParameterSpec = new ECParameterSpec(
				ellipticCurve,
				ecPoint,
				new BigInteger("115792089210356248762697446949407573529996955224135760342422259061068512044369"),
				1);

		KeyPair keyPair;
		try {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
			keyPairGenerator.initialize(ecParameterSpec);
			keyPair = keyPairGenerator.generateKeyPair();
		} catch (Exception ex) {
			throw new IllegalStateException(ex);
		}
		return keyPair;
	}


	/**
	 * 生成RSA密钥对
	 * @param keySize 密钥长度，0表示默认密钥长度
	 * @return RSA密钥对
	 */
	public static RSAKeyPair generateRsaKey(int keySize) throws Exception {
		if(keySize <= 0) {
			keySize = INITIALIZE_LENGTH;
		}
		// 初始化密钥生成器
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(keySize);

		// 生成一对密钥
		KeyPair pair = keyPairGenerator.generateKeyPair();
		RSAPrivateKey privateKey = (RSAPrivateKey) pair.getPrivate();
		RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic();

		// 将私钥和公钥编码为Base64
		String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
		String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
		//System.out.println("公钥：\n" + publicKeyString);
		//System.out.println("私钥：\n" + privateKeyString);
		return new RSAKeyPair(publicKeyString, privateKeyString);
	}

	/**
	 * 生成RSA密钥对
	 * @return RSA密钥对
	 */
	public static RSAKeyPair generateRsaKey() throws Exception {
		return generateRsaKey(0);
	}


	public record RSAKeyPair(String publicKey, String privateKey) {

		public String getPublicKey() {
			return publicKey;
		}

		public String getPrivateKey() {
			return privateKey;
		}
	}
}
